﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Routing;

using ProjectBase.Core;
using ProjectBase.Core.Web;

namespace ProjectBase.Mvc
{
    public class ListView : VisualControl<IListModel>
    {
        #region Render
        protected override void BuildControls()
        {
            base.BuildControls();
            if (Model.IsNull()
                || Model.ItemsToDisplay.IsNull()
                || !Model.ItemsToDisplay.Any())
            {
                Controls.Add
                    (
                        new Paragraph
                        {
                            new Literal(Constants.WebControls.Common.NoRows, true)
                        }
                    );
            }
            else
            {
                Controls.Add(CreateFormForDeletion());
                //Controls.Add(CreateForm());
                Controls.Add(CreateListView());
            }
        }
        #endregion Render

        #region Create
        protected virtual Table CreateListView()
        {
            var isSpecial = Model.RowRenderMode == RowRenderMode.Checkbox
                         || Model.RowRenderMode == RowRenderMode.Radio;
            var table = new Table("list").SetId(isSpecial ? "asyncTable" : "listView");

            if (!Model.HidePagingButtons)
            {
                table.Add(CreateCaption());
            }

            table.AddControls(CreateHead(), CreateBody());

            return table;
        }

        protected virtual Form CreateForm()
        {
            var form = new Form
            {
                CreateListView()
            };

            if (FormSubmitButton.Is())
            {
                form.SetAction(GetFormActionUrl(FormSubmitButton))
                    .SetId(FormSubmitButton.FormIdForJS)
                    .SetName(FormSubmitButton.FormIdForJS);
            }
            return form;
        }
        protected virtual Form CreateFormForDeletion()
        {
            // ready for delete action by [HttpPost]
            var canDelete = Model.RowRenderMode == RowRenderMode.Editable
                          || Model.RowRenderMode == RowRenderMode.Deleteonly;
            return canDelete
                ? new Form().SetAction("/").SetId("doDeleteForm")
                : null;
        }
        #endregion Create

        #region caption
        protected virtual ITableChild CreateCaption()
        {
            // <caption><span>{0}</span></caption>";

            var span = new Span();

            if (Model.Filter.PageCount > 0 || Model.ShowCaptionAlways)
            {
                span.AddControls
                (
                    CreateFirstPageLink(),
                    CreatePreviousPageLink(),
                    CreatePageNumbers(),
                    CreateNextPageLink(),
                    CreateLastPageLink()
                );
            }
            return span.Controls.IsEmpty()
                ? null
                : new Caption { span };
        }

        protected string GetPagingButtonUrl(bool isEnabled, int targetPage)
        {
            if (!isEnabled)
            {
                return Constants.WebControls.Common.EmptyHref;
            }
            return Url.Action(Model.CurrentAction, new { page = targetPage });
        }

        protected virtual Anchor CreateFirstPageLink()
        {
            var disabled = Model.Filter.CurrentPage == 0;
            return new Anchor("paging") { new Literal("\u2502\u25C4\u25C4") }
                .SetHref(disabled ? null : GetPagingButtonUrl(Model.Filter.CurrentPage > 0, 1))
                .SetTitle(disabled ? null : Constants.WebControls.ListView.First.GetLocalized())
                .AddCssClassName(disabled ? "disabled" : null);
        }

        protected virtual Anchor CreatePreviousPageLink()
        {
            var disabled = Model.Filter.CurrentPage == 0;
            return new Anchor("paging") { new Literal("\u25C4") }
                .SetHref(disabled ? null : GetPagingButtonUrl(Model.Filter.CurrentPage > 0,
                    Model.Filter.CurrentPage))
                .SetTitle(disabled ? null : GetLocalized(Constants.WebControls.ListView.Previous))
                .SetAttribute(Attr.AccessKey, Constants.WebControls.ListView.AccessKeyPreviousQ)
                .AddCssClassName(disabled ? "disabled" : null);
        }

        protected virtual Anchor CreateNextPageLink()
        {
            var disabled = Model.Filter.CurrentPage >= Model.Filter.PageCount;
            return new Anchor("paging") { new Literal("\u25BA") }
                .SetHref(disabled ? null : GetPagingButtonUrl(Model.Filter.CurrentPage < Model.Filter.PageCount,
                    Model.Filter.CurrentPage + 2))
                .SetTitle(disabled ? null : GetLocalized(Constants.WebControls.ListView.Next))
                .SetAttribute(Attr.AccessKey, Constants.WebControls.ListView.AccessKeyNextW)
                .AddCssClassName(disabled ? "disabled" : null);
        }

        protected virtual Anchor CreateLastPageLink()
        {
            var disabled = Model.Filter.CurrentPage >= Model.Filter.PageCount;
            return new Anchor("paging") { new Literal("\u25BA\u25BA\u2502") }
                .SetHref(disabled ? null : GetPagingButtonUrl(Model.Filter.CurrentPage < Model.Filter.PageCount,
                    Model.Filter.PageCount + 1))
                .SetTitle(disabled ? null : GetLocalized(Constants.WebControls.ListView.Last))
                .AddCssClassName(disabled ? "disabled" : null);
        }

        protected virtual Span CreatePageNumbers()
        {
            return new Span()
                .SetTitle("{0} ({1}) ".FormatWith(GetLocalized("TotalRowCount"),
                    Model.Filter.TotalRowCount.ToDisplay()))
                .AddControls
                (
                    new Literal("{0} / {1}".FormatWith(
                        (Model.Filter.CurrentPage + 1).ToDisplay(),
                        (Model.Filter.PageCount + 1).ToDisplay())),
                    new Italic
                    {
                        new Literal(" ({0})".FormatWith(
                            (Model.Filter.TotalRowCount).ToDisplay())),
                    }
                );
        }
        #endregion caption

        #region head
        protected virtual TableHeaderCell CreateHeaderCellRadioButtons()
        {
            return new TableHeaderCell("w40 left")
            {
                new Literal(GetLocalized("Select"))
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellCheckBoxes()
        {
            return new TableHeaderCell("w40 center")
            {
                new Input(InputType.CheckBox, "selectAllListed")
                    .SetTitle(GetLocalized("SelectAllListed"))
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellEdit()
        {
            return new TableHeaderCell("w30 left")
            {
                new Literal(GetLocalized(Constants.Actions.Edit))
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellDelete()
        {
            return new TableHeaderCell("w30 right")
            {
                new Literal(GetLocalized(Constants.Actions.NoView.Delete)),
            };
        }

        protected virtual TableHeaderCell CreateHeaderCell(ICellDescription cell)
        {
            // Every item in ItemsToDisplay IsNotNull rendered
            var area = cell.HeaderNameArea.IsNotEmpty()
                           ? cell.HeaderNameArea
                           : Model.CurrentController;

            var header = cell.Localize ? cell.HeaderName.GetLocalized(area) : cell.HeaderName;

            var sortBy = cell.SortProperty ?? cell.HeaderName;
            var sortAction = Model.Filter.OrderBy.ContainsKey(sortBy)
                             && Model.Filter.OrderBy[sortBy]
                                 ? "Desc"
                                 : "Asc";

            if (cell.Sort
                && Model.AllowSorting)
            {
                return new TableHeaderCell
                {
                    new Anchor()
                        .SetTitle(GetLocalized("OrderBy") + Special.Space + header)
                        .SetHref(Url.Action(sortAction,
                            new RouteValueDictionary
                            {
                                //{Attr.Target, Model.CurrentAction},
                                {Constants.WebControls.OrderBy.OrderProperty, sortBy},
                            }))
                        .AddControls
                        (
                            new Literal(header)
                        )
                };
            }

            // <th>{0}</th>
            return new TableHeaderCell
            {
                new Literal(header)
            };
        }

        protected virtual ITableChild CreateHead()
        {
            var row = new TableRow();

            // prepend special
            switch (Model.RowRenderMode)
            {
                case RowRenderMode.Editable:
                    row.Add(Model.ShowEditOnLeft ? CreateHeaderCellEdit() : null);
                    break;
                case RowRenderMode.Editonly:
                    row.Add(Model.ShowEditOnLeft ? CreateHeaderCellEdit() : null);
                    break;
                case RowRenderMode.Checkbox:
                    row.Add(CreateHeaderCellCheckBoxes());
                    break;
                case RowRenderMode.Radio:
                    row.Add(CreateHeaderCellRadioButtons());
                    break;
            }

            // normal columns
            foreach (var cell in Model.ItemsToDisplay.First().Items)
            {
                row.Add(CreateHeaderCell(cell));
            }

            // append special
            switch (Model.RowRenderMode)
            {
                case RowRenderMode.Editable:
                    row.Add(Model.ShowEditOnLeft ? null : CreateHeaderCellEdit());
                    row.Add(CreateHeaderCellDelete());
                    break;
                case RowRenderMode.Editonly:
                    row.Add(Model.ShowEditOnLeft ? null : CreateHeaderCellEdit());
                    break;
                case RowRenderMode.Deleteonly:
                    row.Add(CreateHeaderCellDelete());
                    break;
            }

            return new TableHead { row };
        }
        #endregion head

        #region body
        protected virtual ITableChild CreateBody()
        {
            var body = new TableBody();

            var isOdd = true;
            var rowNumber = 0;
            foreach (var item in Model.ItemsToDisplay)
            {
                body.Add(CreateRowForItem(item, isOdd, rowNumber++));
                isOdd = !isOdd;
            }

            return body;
        }

        #region row
        protected static string GetRowClass(IItemToDisplay item, bool isOdd)
        {
            var css = isOdd ? "odd " : string.Empty;
            return css + item.TableRowCss;
        }

        protected virtual ITableRow CreateRowForItem(IItemToDisplay item, bool isOdd, int rowNumber)
        {
            // row
            var row = new TableRow(GetRowClass(item, isOdd));

            // prepend special
            switch (Model.RowRenderMode)
            {
                case RowRenderMode.Editable:
                    row.Add(Model.ShowEditOnLeft ? CreateCellEditForItem(item) : null);
                    break;
                case RowRenderMode.Editonly:
                    row.Add(Model.ShowEditOnLeft ? CreateCellEditForItem(item) : null);
                    break;
                case RowRenderMode.Checkbox:
                    row.Add(CreateCellSelectForItem(item, InputType.CheckBox));
                    break;
                case RowRenderMode.Radio:
                    row.Add(CreateCellSelectForItem(item, InputType.Radio));
                    break;
            }



            var columnNumber = 0;
            foreach (var cell in item.Items)
            {
                // cell
                row.Add(CreateCellForItem(item, cell, rowNumber, columnNumber++));
            }

            // append special
            switch (Model.RowRenderMode)
            {
                case RowRenderMode.Editable:
                    row.Add(Model.ShowEditOnLeft ? null : CreateCellEditForItem(item));
                    row.Add(CreateCellDeleteForItem(item));
                    break;
                case RowRenderMode.Editonly:
                    row.Add(Model.ShowEditOnLeft ? null : CreateCellEditForItem(item));
                    break;
                case RowRenderMode.Deleteonly:
                    row.Add(CreateCellDeleteForItem(item));
                    break;
            }

            return row;
        }

        protected virtual TableCell CreateCellSelectForItem(IItemToDisplay item, InputType inputType)
        {
            return new TableCell("center")
            {
                new Input(inputType)
                    .SetValue(item.ID)
                    .SetName(inputType.ToString().ToLowerInvariant())
                    .SetAttribute("data-displayname", item.Description)
            };
        }

        protected virtual TableCell CreateCellEditForItem(IItemToDisplay item)
        {
            var additionalParameters = Model.AdditionalParameters;
            additionalParameters[Constants.Common.ID] = item.ID;

            return new TableCell("w30")
            {
                !item.CanBeEdited ? null :
                new Anchor()
                    .SetHref(Url.Action(Constants.Actions.Edit, Model.CurrentController, additionalParameters))
                    .SetTitle(Constants.Actions.Edit.GetLocalized())
                    .SetTarget(Model.TargetNameForLink)
                    .AddControls
                    (
                        new Literal(Constants.Actions.Edit.GetLocalized())
                    )
            };
        }

        protected virtual TableCell CreateCellDeleteForItem(IItemToDisplay item)
        {
            var additionalParameters = Model.AdditionalDeleteParameters;
            additionalParameters[Constants.Common.ID] = item.ID;

            var hrefDelete = Url.Action(Constants.Actions.NoView.Delete, Model.CurrentController, additionalParameters);

            var message = Constants.WebControls.Common.DoDelete2.GetLocalized().FormatWith(item.ID, item.Description);
            var assureDelete = message.Replace('\'', ' ');

            return new TableCell("w30 redC")
            {
                !item.CanBeDeleted ? null :
                new Anchor("center") { new Literal("X") }
                    .AddCssClassName("assureDelete")
                    .SetHref(hrefDelete)
                    .SetTitle(Constants.WebControls.Common.Delete.GetLocalized())
                    .SetAttribute("data-assuremessage", assureDelete)
            };
        }

        protected virtual TableCell CreateCellForItem(IItemToDisplay item, ICellDescription cell, int rowNumber, int columnNumber)
        {
            if (cell.IsBoolean)
            {
                return new TableCell
                {
                    new Input(InputType.CheckBox)
                        .SetChecked(cell.Value.IsEqual("true"))
                        .SetDisabled(true)
                }.AddCssClassName(cell.Align.ToString());
            }

            var anchor = new Anchor()
                .AddCssClassName(cell.Align.ToString())
                .AddCssClassName(Model.ShowDetailAction ? null : " noPointer ")
                .SetTitle(cell.Value.IsNotEmpty() && cell.Value.Length > cell.MaxCellLength ? cell.Value : null)
                .SetTarget(Model.TargetNameForLink)
                .SetAttribute(Attr.AccessKey, columnNumber.Equals(0) && rowNumber < 9 ? (rowNumber + 1).ToString() : null)
                .AddControls
                (
                    new Literal((cell.Value.ToLength(cell.MaxCellLength, true)))
                );

            if (!Model.ShowDetailAction)
            {
                anchor.SetHref(Constants.WebControls.Common.EmptyHref);
            }
            else
            {
                var additionalParameters = Model.AdditionalParameters;
                additionalParameters[Constants.Common.ID] = item.ID;
                anchor.SetHref(Url.Action(Constants.Actions.Detail, Model.CurrentController, additionalParameters));
            }

            return new TableCell { anchor };
        }
        #endregion row

        #endregion body

        #region properties
        public virtual IButtonItem FormSubmitButton { get; set; }
        #endregion properties
    }
}